<template>
  <el-dialog
    v-model="dialogVisible"
    :destroy-on-close="true"
    :title="!dialogParam.title ? '弹出框' : dialogParam.title"
    class="selectDialog"
    @close="handleCancel"
  >
    <div>
      <el-row class="dialog-style">
        <el-col :span="12" class="dialog-style-left scrollbar">
          <el-input
            v-model="filterText"
            class="mb-15px"
            placeholder="请输入关键字"
          />
          <div v-if="useList && useList.length > 0" class="useListSty">
            <div class="mb-15px text-#000 blod">常用人员：</div>
            <span
              v-for="(item, index) in useList"
              :key="index"
              :class="{ active: isACtive(item) }"
              @click="useClick(item)"
              >{{ item.label }}</span
            >
          </div>
          <div class="text-#000 blod mt-10px">联系人员：</div>
          <div style="overflow: auto; height: 55vh">
            <el-tree
              ref="treeRef"
              :check-on-click-node="true"
              :check-strictly="dialogObj.checkStrictly"
              :class="dialogObj.multiple ? '' : 'customNodeClass'"
              :data="dialogObj.data"
              :default-checked-keys="dialogObj.defaultCheckedKeys"
              :default-expand-all="defaultExpandAll"
              :default-expanded-keys="defaultExpandedKeys"
              :expand-on-click-node="false"
              :filter-node-method="filterNode"
              :node-key="dialogObj.nodeKey"
              show-checkbox
              @check-change="nodeClick"
            />
          </div>
        </el-col>
        <el-col :span="12" class="dialog-style-right">
          <el-row>
            <el-col :span="18">已选</el-col>
            <el-col :span="6" class="clear" @click="handleClear()">清空</el-col>
          </el-row>
          <ul class="dialog-style-list">
            <li
              v-for="item in selectData"
              :key="item.value"
              @click="!item.disabled ? handleDel(item) : ''"
            >
              {{ item.label }}
              <span v-if="!item.disabled">×</span>
            </li>
          </ul>
        </el-col>
      </el-row>
    </div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="handleCancel">取消</el-button>
        <el-button type="primary" @click="handleAffirm"> 确认 </el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script name="SelectDialog" setup>
import { ElTree } from 'element-plus'
import { getUserlist, userInsert } from '@/api/common/common'
import { getCurrentInstance, nextTick, watchEffect } from 'vue'
import useCommonStore from '@/store/modules/common'

const { proxy } = getCurrentInstance()
// 通用数据store
const commonStore = useCommonStore()
// 接受父级传递的参数
const props = defineProps({
  dialogParam: {
    required: true,
    type: Object || Array,
    default: () => {
      return {}
    }
  }
})
const treeRef = ref(ElTree)
// 选中的数据
const selectData = ref([])
// 弹出框是否隐藏
const dialogVisible = ref(false)
// 2023-5-12 新增
// 默认展开的节点
const defaultExpandedKeys = ref([])
// 默认展开所有节点
const defaultExpandAll = ref(true)

//设置参数
const dialogObj = reactive({
  // avue-tree 的数据
  data: [], // tree的数据
  multiple: false, //是否多选
  checkStrictly: false, //是否遵循父子不互相关联的做法，默认为 false
  nodeKey: props.dialogParam.nodeKey || 'id', //值默认id
  defaultCheckedKeys: [] //默认选中的值key
})
// 搜索关键字
const filterText = ref('')
watch(filterText, val => {
  !treeRef.value.filter(val)
})
watchEffect(
  () => {
    dialogVisible.value = props.dialogParam.isDialog // 表单弹出框
    dialogObj.defaultCheckedKeys = props.dialogParam.defaultCheckedKeys
    //获取tree数据
    getTreeData()
    dialogObj.multiple = props.dialogParam.multiple //是否多选
    dialogObj.checkStrictly = props.dialogParam.checkStrictly //是否遵循父子不互相关联的做法
    dialogObj.nodeKey = props.dialogParam.nodeKey
  },
  {
    flush: 'post'
  }
)

const getTreeData = async () => {
  if (props.dialogParam.data) {
    dialogObj.data = props.dialogParam.data // tree的数据
  } else {
    console.log(props.dialogParam, 'props.dialogParam--')
    switch (props.dialogParam.dataType) {
      case 'person':
        console.log(props.dialogParam, 'props.dialogParam----')
        let params = null
        defaultExpandAll.value = false
        //   判断是否传参
        if (props.dialogParam.apiParams) {
          params = props.dialogParam.apiParams
        }
        // 获取人员数据
        let res = await commonStore.getUseTreeData(params)
        dialogObj.data = res
        let sData = [...props.dialogParam.defaultCheckedKeys]
        if (!sData[0] && res && res.length > 0) {
          // 初始化默认第一个节点展开
          defaultExpandedKeys.value = [res[0][dialogObj.nodeKey]]
        } else if (sData[0] && sData[0].toString().indexOf('U') == -1) {
          // 当传过来的默认值没有带U的时候，自动加上U
          let newData = []
          sData.forEach(item => {
            newData.push('U' + item)
          })
          dialogObj.defaultCheckedKeys = newData
        } else {
          // 当传过的值是带U的时候 单选则默认选中的值 节点展开，多选则展开第一个节点
          defaultExpandedKeys.value = dialogObj.multiple
            ? res && res.length > 0
              ? [res[0][dialogObj.nodeKey]]
              : []
            : dialogObj.defaultCheckedKeys
        }
        break
    }
  }
  if (props.dialogParam.defaultCheckedKeys != undefined) {
    nextTick(() => {
      if (treeRef.value) {
        // try {
        let sData = treeRef.value.getCheckedNodes() //获取选中的值
        selectData.value = dialogObj.checkStrictly
          ? sData
          : sData.filter(item => !item.children)
        // } catch (error) {
        //   console.log(error, 'selectDialog组件错误')
        // }
      }
    })
  }
  await getUserListFn()
}

// 过滤节点
const filterNode = (value, data, node) => {
  if (!value) return true
  let _array = [] //这里使用数组存储 只是为了存储值。
  getReturnNode(node, _array, value)
  let result = false
  _array.forEach(item => {
    result = result || item
  })
  return result
}
// 获取过滤节点的子节点
const getReturnNode = (node, _array, value) => {
  let isPass =
    (node.data && node.data.label && node.data.label.indexOf(value) !== -1) ||
    (value.length >= 4 && String(node.data.userName).startsWith(value))
  isPass ? _array.push(isPass) : ''
  if (!isPass && node.level != 1 && node.parent) {
    getReturnNode(node.parent, _array, value)
  }
}

// tree点击选中
const nodeClick = (data, checked) => {
  if (!dialogObj.multiple) {
    if (checked) {
      dialogObj.defaultCheckedKeys = [data[dialogObj.nodeKey]]
      treeRef.value.setCheckedKeys([data[dialogObj.nodeKey]])
    } else {
      if (
        dialogObj.defaultCheckedKeys &&
        dialogObj.defaultCheckedKeys[0] === data[dialogObj.nodeKey]
      ) {
        treeRef.value.setCheckedKeys([data[dialogObj.nodeKey]])
      }
    }
  }
  let sData = treeRef.value.getCheckedNodes() //获取选中的值
  selectData.value = dialogObj.checkStrictly
    ? sData
    : sData.filter(item => !item.children && item.uuid.indexOf('D') == -1)

  useSelect.value = sData
    ? useList.value.filter(item =>
        selectData.value.some(obj => obj.uuid === item.uuid)
      )
    : []
}
const emit = defineEmits(['ok', 'close'])
// 确认操作
const handleAffirm = () => {
  let sData = [...selectData.value]
  let labelData = [],
    defaultCheckedKeys = []
  sData.forEach(item => {
    labelData.push(item.label)
    defaultCheckedKeys.push(item[dialogObj.nodeKey])
  })
  //插入常用人数据
  userInsert({
    type: useType.value,
    list: sData
  })
  emit('ok', {
    type: props.dialogParam.type,
    selectData: sData,
    labelData: labelData, // 选中的数据label
    defaultCheckedKeys: defaultCheckedKeys, // 选中的数据id
    dialogVisible: false
  })
  reset()
}
// 取消操作
const handleCancel = () => {
  reset()
  emit('close')
}
// 删除选中数据
const handleDel = val => {
  let sData = [...selectData.value]
  selectData.value = sData.filter(
    item => item[dialogObj.nodeKey] != val[dialogObj.nodeKey]
  )
  treeRef.value.setCheckedNodes(selectData.value, false)
  dialogObj.defaultCheckedKeys = []
}
// 清空数据
const handleClear = () => {
  let sData = treeRef.value.getCheckedNodes() //获取选中的值
  // 去掉父级选中的数据（当父级下的子集所有的数据都被选中的时候，父级会默认被选中，所以要删除父级选中的数据）
  let newData = dialogObj.checkStrictly
    ? sData
    : sData.filter(item => !item.children)
  let isClear = newData.map(item => item.disabled == true)
  if (isClear && isClear[0]) {
    proxy.$modal.msgError('存在不能删除的数据')
    return false
  }
  treeRef.value.setCheckedNodes([], false)
  selectData.value = []
  dialogObj.defaultCheckedKeys = []
  useSelect.value = []
}
const reset = () => {
  dialogVisible.value = false
  dialogObj.data = []
  selectData.value = []
  dialogObj.defaultCheckedKeys = []
  filterText.value = ''
  useSelect.value = []
}
/** 常用人 start*/
const useList = ref([])
//获取常用人员的列表（针对业务的）
const useType = computed(() => {
  return props.dialogParam.useType || 'commonPersonnel'
})
const getUserListFn = async () => {
  let res = await getUserlist({ type: useType.value })
  useList.value =
    res.data && res.data.length > 0
      ? res.data.filter(item => {
          return findInNestedChildren(dialogObj.data, item.uuid)
        })
      : []
  useSelect.value = selectData.value
}
const useSelect = ref([])
const isACtive = item => {
  const selectedData =
    useSelect.value && JSON.stringify(useSelect.value) != '[]'
      ? useSelect.value.find(selected => selected.uuid === item.uuid)
      : null
  return selectedData ? true : false
}
// 常用人员-点击选中
const useClick = item => {
  if (dialogObj.multiple) {
    const selectedData =
      useSelect.value && JSON.stringify(useSelect.value) != '[]'
        ? useSelect.value.find(selected => selected.uuid === item.uuid)
        : null
    if (selectedData) {
      useSelect.value = useSelect.value.filter(
        selected => selected.uuid !== item.uuid
      )
      selectData.value = selectData.value.filter(
        selected => selected.uuid !== item.uuid
      )
    } else {
      useSelect.value.push(item)
    }
    let sumUser = [].concat(selectData.value, useSelect.value)
    let newUser = removeDuplicates(sumUser, 'uuid')
    selectData.value = newUser
    treeRef.value.setCheckedNodes(newUser, false)
    dialogObj.defaultCheckedKeys = []
  } else {
    useSelect.value = [item]
    selectData.value = [item]
    treeRef.value.setCheckedNodes([item], false)
    dialogObj.defaultCheckedKeys = []
  }
}

/**
 * 去重
 * arr 数组
 * field 字段名
 * */
function removeDuplicates(arr, field) {
  const uniqueSet = new Set()
  const result = []

  for (let i = 0; i < arr.length; i++) {
    const item = arr[i]
    if (!uniqueSet.has(item[field])) {
      uniqueSet.add(item[field])
      result.push(item)
    }
  }

  return result
}

const findInNestedChildren = (arr, uuid) => {
  for (let i = 0; i < arr.length; i++) {
    const item = arr[i]
    if (item.uuid === uuid) {
      return true
    }
    if (item.children && item.children.length > 0) {
      const found = findInNestedChildren(item.children, uuid)
      if (found) {
        return true
      }
    }
  }
  return false
}

/** 常用人 end*/
</script>
<style lang="scss" scoped>
/* 隐藏不选节点 */
::v-deep .el-tree .el-tree-node__content .is-disabled {
  display: none !important;
}

ul,
li {
  margin: 0;
  margin-block-end: 0;
  margin-block-start: 0;
}

.dialog-style {
  @apply mt--20px;
  .dialog-style-left {
    border-right: 1px solid #ccc;
    @apply pr-20px;
    overflow: auto;

    .customNodeClass {
      :deep(.el-checkbox__inner) {
        @apply rounded-50;
      }
    }
  }

  .dialog-style-right {
    @apply leading-30px pl-20px  cursor-pointer;
    .clear {
      color: var(--el-color-primary);
      @apply text-right;
    }
  }

  .dialog-style-list {
    @apply mt-15px ml--40px  leading-20px;
    li {
      color: #999;
      background-color: #f5f5f5;
      @apply flex list-none pl-15px pt-5px pb-5px mb-10px rounded-35px;
      span {
        color: var(--el-color-primary);
        @apply flex-1 text-right pr-15px cursor-pointer;
      }
    }
  }
}

/**滚动条**/
/*整个滚动条*/
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

/*滚动槽*/
::-webkit-scrollbar-track {
  background-color: #f5f5f5;
}

/*滚动条上滑块*/
::-webkit-scrollbar-thumb {
  background-color: #c1c1c1;
  border-radius: 16px;
  height: 30px;
  border: 1px solid #f5f5f5;
}

/*滚动条下滑块*/
::-webkit-scrollbar-thumb:hover {
  background-color: #555;
}

/*右侧距离*/
body::-webkit-scrollbar-corner {
  background-color: #f5f5f5;
}

/* Firefox 的兼容方式 */
html {
  scrollbar-width: thin;
  scrollbar-color: #c1c1c1 #f5f5f5;
}

/* 滚动条整体 */
.scrollbar {
  scrollbar-width: thin;
}

/* 滚动槽 */
.scrollbar::-moz-scrollbar-track {
  background-color: #ccc;
  border-radius: 4px;
}

/* 滑块 */
.scrollbar::-moz-scrollbar-thumb {
  background-color: #999;
  border-radius: 4px;
}

/* 悬停状态时的滑块颜色 */
.scrollbar::-moz-scrollbar-thumb:hover {
  background-color: #666;
}

/* Edge */
body::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.useListSty {
  span {
    background: #f5f5f5;
    padding: 6px 10px;
    margin: 0px 5px 10px;
    border-radius: 8px;
    display: inline-block;
    cursor: pointer;

    &.active {
      background: #1890ff;
      color: #fff;
    }
  }
}
</style>
